package owlapps2012.owlToSql.base;

import java.io.FileInputStream;
import java.util.Properties;
import java.util.Set;

/**
* Author: Piotr Nowara<br>
* piotrnowara@gmail.com<br>
* code made available under Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.html)<br>
* copyright 2012, Piotr Nowara<br>
*/
public class DynamicAppConfig extends DefaultAppConfig
{

	private static final String DATE_COLUMN_NAME_PARAM_NAME = "DateColumn";
	private static final String ID_COLUMN_NAME_PARAM_NAME = "IdColumn";
	private static final String SQL_TYPE_PARAM_NAME = "SQLType";
	private static final String DOMAIN_CLASS_MAPPING_PARAM_NAME = "DomainClassMapping";
	private static final String DOMAIN_PROPERTY_MAPPING_PARAM_NAME = "DomainPropertyMapping";
	private static final String DOMAIN_NUMERIC_PROPERTY_MAPPING_PARAM_NAME = "DomainNumericPropertyMapping";
	private static final String ADDITIONAL_CONDITION_PARAM_NAME = "AdditionalCondition";
	private static final String HIERARCHICAL_OBJECT_FLAG = "H";
	private Properties config = new Properties();

	public DynamicAppConfig(String configFilePath) throws Exception 
	{
		this.config.load(new FileInputStream(configFilePath));
		this.initConf();
	}

	private void initConfFromParams() throws Exception 
	{
		System.out.println(config.keySet());
		Set<Object> parameters = config.keySet();
		for(Object param : parameters)
		{
			String paramName = (String)param;
			System.out.println(paramName);
			if(paramName.equals(DATE_COLUMN_NAME_PARAM_NAME))
			{
				this.dateColumn = config.getProperty(DATE_COLUMN_NAME_PARAM_NAME, super.dateColumn);
			}
			else if(paramName.equals(ID_COLUMN_NAME_PARAM_NAME))
			{
				this.idColumn = config.getProperty(ID_COLUMN_NAME_PARAM_NAME, super.idColumn);
			}
			else if(paramName.equals(SQL_TYPE_PARAM_NAME))
			{
				this.sqlType = SQLType.getSqlTypeByName(config.getProperty(SQL_TYPE_PARAM_NAME).toUpperCase());
				if(this.sqlType == null)
					throw new Exception("SQL_TYPE_PARAM_NAME - unsupported SQL dialect: "+config.getProperty(SQL_TYPE_PARAM_NAME));
			}
			else if(paramName.startsWith(DOMAIN_PROPERTY_MAPPING_PARAM_NAME))
			{
				String domainPropertyName;
				try {
					domainPropertyName = paramName.split("-")[1];
				} catch (Exception e) {
					throw new Exception(DOMAIN_PROPERTY_MAPPING_PARAM_NAME + " parameter without suffix.", e);
				}
				String[] mappings = config.getProperty(paramName).split(",");
				if(mappings.length == 3)
				{
					if(mappings[2].equals(HIERARCHICAL_OBJECT_FLAG))
						this.addDomainPropertyMapping(new DomainPropertyMapping(domainPropertyName, "{Q}."+mappings[0]+" LIKE '{VALUE}%'", mappings[1]));
					else
						throw new Exception(DOMAIN_PROPERTY_MAPPING_PARAM_NAME + "- unrecognized value of hierarchical flag: "+mappings[2]);
				}
				else if(mappings.length == 2)
					this.addDomainPropertyMapping(new DomainPropertyMapping(domainPropertyName, "{Q}."+mappings[0]+" = '{VALUE}'", mappings[1]));
				else
					throw new Exception(DOMAIN_PROPERTY_MAPPING_PARAM_NAME + " param must have 2 or 3 values separated by a comma.");
			}
			else if(paramName.startsWith(DOMAIN_NUMERIC_PROPERTY_MAPPING_PARAM_NAME))
			{
				String domainPropertyName;
				try {
					domainPropertyName = paramName.split("-")[1];
				} catch (Exception e) {
					throw new Exception(DOMAIN_NUMERIC_PROPERTY_MAPPING_PARAM_NAME + " parameter without suffix.", e);
				}
				String[] mappings = config.getProperty(paramName).split(",");
				if(mappings.length == 2)
					this.addDomainPropertyMapping(new DomainPropertyMapping(domainPropertyName, "{Q}."+mappings[0]+" = {VALUE}", mappings[1]));
				else
					throw new Exception(DOMAIN_NUMERIC_PROPERTY_MAPPING_PARAM_NAME + " param must have 2 values separated by a comma.");
			}
			else if(paramName.startsWith(DOMAIN_CLASS_MAPPING_PARAM_NAME))
			{
				String domainClassName;
				try {
					domainClassName = paramName.split("-")[1];
				} catch (Exception e) {
					throw new Exception(DOMAIN_CLASS_MAPPING_PARAM_NAME + " parameter without suffix.", e);
				}
				this.addDomainClassMapping(new DomainClassMapping(domainClassName, config.getProperty(paramName)));
			}
			else if(paramName.startsWith(ADDITIONAL_CONDITION_PARAM_NAME))
			{
				String conditionName;
				try {
					conditionName = paramName.split("-")[1];
				} catch (Exception e) {
					throw new Exception(ADDITIONAL_CONDITION_PARAM_NAME + " parameter without suffix.", e);
				}
				this.additionalConditions.put(conditionName, config.getProperty(paramName));

			}
			else
				throw new Exception("Unsupported parameter: "+ paramName);
				
		}		
	}

	@Override
	protected void initConf() throws Exception 
	{
		if(config != null)
			this.initConfFromParams();
	}

}
